package com.waqu.common.utils.waqu;


import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;

import com.waqu.common.utils.collection.ArrayMapTools;
import com.waqu.common.utils.text.StringTools;

/**
 * @ClassName SerialNoGenerator
 * @Description ID生成器
 * @author tangjunfeng
 * @date 2017年5月25日 下午5:16:59
 */
public class SerialNoGenerator {

	// 靓号过滤类型正则，如AABBCD，符合数字有112234，336627等
	private static final String ABCABC = "^(\\d{3})\\1$";
	private static final String AABBCC = "^(\\d)\\1(\\d)\\2(\\d)\\3$";
	private static final String AAXBBX = "^(\\d)\\1\\d(\\d)\\2\\d$";
	private static final String LOVE6S = "^(520|521|1314|3344)\\d+$";
	
	private static final String ABCABCX = "^(\\d{3})\\1\\d$";
	private static final String ABABABC = "^(\\d{2})\\1\\1\\d$";
	private static final String AABBCCX = "^(\\d)\\1(\\d)\\2(\\d)\\3\\d$";
	private static final String XAABBCC = "^\\d(\\d)\\1(\\d)\\2(\\d)\\3$";
	private static final String AAABBBC = "^(\\d)\\1\\1(\\d)\\2\\2\\d$";
	private static final String CAAABBB = "^\\d(\\d)\\1\\1(\\d)\\2\\2$";
	private static final String AAAXBBB = "^(\\d)\\1\\1\\d(\\d)\\2\\2$";
	
    // 靓号过滤相同连续数字的种子
	private static final String[] seeds_3 = {"111","222","333","444","555","666","777","888","999","000"};
	private static final String[] seeds_4 = {"1111","2222","3333","4444","5555","6666","7777","8888","9999","0000"};
	private static final String[] seeds_5 = {"11111","22222","33333","44444","55555","66666","77777","88888","99999","00000"};
	private static final String[] seeds_6 = {"111111","222222","333333","444444","555555","666666","777777","888888","999999","000000"};
	private static final String[] seeds_7 = {"1111111","2222222","3333333","4444444","5555555","6666666","7777777","8888888","9999999","0000000"};
	private static final String[] seeds_8 = {"11111111","22222222","33333333","44444444","55555555","66666666","77777777","88888888","99999999","00000000"};
	private static final String[] seeds_9 = {"111111111","222222222","333333333","444444444","555555555","666666666","777777777","888888888","999999999","000000000"};
    
    // 靓号中 4位、5位、7顺子
    private static final String[] specialNumbers_4 = { "1234", "2345", "3456", "4567", "5678", "6789","7890", "9876", "8765", "7654", "6543", "5432", "4321" };
	private static final String[] specialNumbers_5 = { "12345", "23456", "34567", "45678", "56789", "98765", "87654", "76543", "65432", "54321" };
	private static final String[] specialNumbers_6 = { "123456", "234567", "345678", "456789", "987654", "876543", "765432", "654321" };
	private static final String[] specialNumbers_7 = { "1234567", "2345678", "3456789", "9876543", "8765432", "7654321" };
	private static final String[] specialNumbers_8 = { "12345678", "23456789", "34567890", "98765432", "87654321", "76543210" };
	private static final String[] specialNumbers_9 = { "123456789", "234567890", "987654321", "876543210" };
	
	private static final int minSerialNo = 100000;
	private static final int maxSerialNo = 999999999;

    /**
     *
     * 按照靓号规则，自动排除靓号，生成普通娃趣ID
     * 目前从6位数字开始
     * @param start 起始数字
     * @return
     */
	public static Integer generateNormalSerialNo(Integer start) {
		List<Integer> serialNo = batchGenerateNormalSerialNo(start, 1);
		return ArrayMapTools.isNotEmpty(serialNo) ? serialNo.get(0) : null;
	}



    /**
     * 批量生产娃趣号
     * @param start 起始值
     * @param size 批量生产的数量
     * @return
     */
	public static List<Integer> batchGenerateNormalSerialNo(int start, int size) {
		if (start < minSerialNo || size <= 0 || start > maxSerialNo)
			return null;
		
		List<Integer> results = new ArrayList<Integer>();
		String tempSerialNo = null;
		for (int i = start; i <= maxSerialNo && results.size() < size; i++) {
			tempSerialNo = String.valueOf(i);
			// 字符串中包含1-2种数字
			if (isDuplicateCount(tempSerialNo))
				continue;
			// 通用规则排除，顺子号-递增
			if (isOrderNumer(tempSerialNo))
				continue;
			// 相同数字
			if (isSameChars(tempSerialNo))
				continue;
			// 指定格式类型判断
			if (isCustomStyleNumber(tempSerialNo))
				continue;
			results.add(i);
		}
		return results;
	}


    /**
     * 批量生产靓号
     * @param start 起始值
     * @return
     */
	public static List<Integer> batchGenerateBeautifulSerialNo(int start, int size) {
		if (start < minSerialNo || start > maxSerialNo || size <= 0)
			return null;

		List<Integer> results = new ArrayList<Integer>();
		String tempSerialNo = null;
		for (int i = start; i <= maxSerialNo && results.size() < size; i++) {
			tempSerialNo = String.valueOf(i);
			// 字符串中包含1-2种数字
			if (isDuplicateCount(tempSerialNo)) {
				results.add(i);
				continue;
			}
			// 通用规则排除，顺子号-递增
			if (isOrderNumer(tempSerialNo)) {
				results.add(i);
				continue;
			}
			if (isSameChars(tempSerialNo)) {
				results.add(i);
				continue;
			}
			// 指定格式类型判断
			if (isCustomStyleNumber(tempSerialNo)) {
				results.add(i);
				continue;
			}
		}
		return results;
	}

	/** 排除顺子号 */
    private static boolean isOrderNumer(String serialNo) {
		return traverseSeeds(specialNumbers_4, serialNo) || traverseSeeds(specialNumbers_5, serialNo)
				|| traverseSeeds(specialNumbers_6, serialNo) || traverseSeeds(specialNumbers_7, serialNo)
				|| traverseSeeds(specialNumbers_8, serialNo) || traverseSeeds(specialNumbers_9, serialNo);
	}


    /**
     *
     * 判断是否包含相同数字
     * @param srcNumber
     *        需要判断的数字
     * @return
     */
    private static boolean isSameChars(String srcNumber){
        if(srcNumber.length() == 6) {
            if(traverseSeeds(seeds_3,srcNumber) || traverseSeeds(seeds_4,srcNumber) || traverseSeeds(seeds_5,srcNumber))
            	return true;
        }
        return traverseSeeds(seeds_4,srcNumber) || traverseSeeds(seeds_5,srcNumber) || traverseSeeds(seeds_6,srcNumber)
        		|| traverseSeeds(seeds_7,srcNumber) || traverseSeeds(seeds_8,srcNumber) || traverseSeeds(seeds_9,srcNumber);
    }


	/**
	 * 字符串中的数字个数为字符串长度的1/2(有小数则向下取整)则为靓号<br/>
	 * 如：123123则为靓号，1234123则为靓号
	 */
    private static boolean isDuplicateCount(String serialNo) {
		if (StringTools.isEmpty(serialNo) || StringTools.isBlank(serialNo))
			return false;
		int half = serialNo.length() / 2;
		if (serialNo.length() % 2 == 0)
			half--; // 偶数长度取 1/2 - 1
		return getNotDuplicateCount(serialNo) <= half;
	}

	private static boolean traverseSeeds(String[] seeds, String src) {
		boolean result = false;
		for (String s : seeds) {
			if (src.indexOf(s) > -1) {
				result = true;
				break;
			}
		}
		return result;
	}

	/** 获取字符串中非重复的字符数 */
	private static int getNotDuplicateCount(String serialNo) {
		Set<Character> counter = new HashSet<>();
		for (char temp : serialNo.toCharArray()) {
			counter.add(temp);
		}
		return counter.size();
	}


    /**
     * 判断是否是生日号码（19开头的）
     * @param src
     * @return
     */
	private static boolean isBirthDayNumber(String src){
        if(StringUtils.isBlank(src)){
            return false;
        }

        if(src.length() != 6){
            return false;
        }
        return src.startsWith("19");
    }


    /**
     * 判断给定格式的数字格式
     * @param src
     * @return
     */
	private static boolean isCustomStyleNumber(String src) {
		if (src.length() == 6) {
			if (matcherRegx(ABCABC, src) || matcherRegx(AABBCC, src) || matcherRegx(AAXBBX, src)
					|| matcherRegx(LOVE6S, src))
				return true;
		}
		return matcherRegx(ABCABCX, src) || matcherRegx(ABABABC, src) || matcherRegx(AABBCCX, src)
				|| matcherRegx(XAABBCC, src) || matcherRegx(AAABBBC, src) || matcherRegx(CAAABBB, src)
				|| matcherRegx(AAAXBBB, src) || matcherRegx(LOVE6S, src);
	}

    /**
     * 编译正则
     * @param regx
     * @param src
     * @return
     */
    private static boolean matcherRegx(String regx,String src){
        Pattern p = Pattern.compile(regx);
        Matcher m  = p.matcher(src);
        return m.matches();
    }
    
}
